package com.longlinkislong.games;

import java.io.IOException;
import java.io.InputStream;

import com.longlinkislong.util.LittleEndianDataInputStream;

public class Model3DS {
	private static final int C_MAIN3DS	= 0x4d4d;
	private static final int C_EDIT3DS	= 0x3d3d;
	private static final int C_EDITOBJ	= 0x4000;
	private static final int C_TRIMESH 	= 0x4100;
	private static final int C_TRIVERT	= 0x4110;
	private static final int C_TFACEL1	= 0x4120;
	private static final int C_TMCOORD	= 0x4140;
	
	private char name[] = new char[20];
	public Tuple<Float>[] vertices;
	public Tuple<Integer>[] polygons;
	public Duple<Float>[] mapcoords;
	
	public String getName(){
		return new String(name);
	}
	
	@SuppressWarnings("unchecked")
	public Model3DS(final InputStream in) throws IOException{
		final LittleEndianDataInputStream pIn = new LittleEndianDataInputStream(in);
		
		int i, lChunkId, lQTY;
		long lChunkLength;
		char lChar;
		
		readLoop: while(true){
			try{
				lChunkId = pIn.readUnsignedShort();
			}catch(Exception e){
				break readLoop;
			}
			lChunkLength = pIn.readUnsignedInt();
			
			switch(lChunkId){
				case C_MAIN3DS:
					break;
				case C_EDIT3DS:
				case C_TRIMESH:
					break;
				case C_EDITOBJ:
					i = 0;
					do {
						lChar = (char) pIn.readUnsignedByte();
						this.name[i] = lChar;
						i++;
					} while(lChar != '\0' && i < 20);
					break;
				case C_TRIVERT:
					lQTY = pIn.readUnsignedShort();					
					this.vertices = new Tuple[lQTY];
					
					for(i = 0; i < lQTY; i++){
						this.vertices[i] = new Tuple<Float>();
						this.vertices[i].x = pIn.readFloat();
						this.vertices[i].y = pIn.readFloat();
						this.vertices[i].z = pIn.readFloat();						
					}
					break;
				case C_TFACEL1:
					lQTY = pIn.readUnsignedShort();
					this.polygons = new Tuple[lQTY];
					
					for(i = 0; i < lQTY; i++){
						final int a = pIn.readUnsignedShort();
						final int b = pIn.readUnsignedShort();
						final int c = pIn.readUnsignedShort();
						
						pIn.readUnsignedShort();
						
						this.polygons[i] = new Tuple<Integer>(a, b, c);
					}
					break;
				case C_TMCOORD:
					lQTY = pIn.readUnsignedShort();
					this.mapcoords = new Duple[lQTY];
					for(i = 0; i < lQTY; i++){
						final float u = pIn.readFloat();
						final float v = pIn.readFloat();
						
						this.mapcoords[i] = new Duple<Float>(u, v);
					}
					break;
				default:
					pIn.skip(lChunkLength - 6);
			}
		}
		pIn.close();
	}
	public class Tuple<T extends Number>{
		public Tuple(){}
		public Tuple(T x, T y, T z){
			this.x = x;
			this.y = y;
			this.z = z;
		}
		public T x, y, z;
	}
	public class Duple<T extends Number>{
		public Duple(){}
		public Duple(T x, T y){
			this.x = x;
			this. y = y;
		}
		public T x, y;
	}
}
